#include "gobangwindow.h"
#include <QMessageBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QTime>
#include <QDebug>

GobangWindow::GobangWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // 初始化游戏状态
    initGame();

    // 初始化UI
    initUI();

    // 设置窗口属性
    setWindowTitle("五子棋 - 双人对战");
    setMinimumSize(800, 600);
}

GobangWindow::~GobangWindow()
{
    timer->stop();
    delete timer;
}

void GobangWindow::initGame()
{
    // 初始化棋盘
    for (int i = 0; i < BOARD_SIZE; ++i) {
        for (int j = 0; j < BOARD_SIZE; ++j) {
            board[i][j] = 0;
        }
    }

    // 初始化游戏状态
    isBlackTurn = true;
    gameOver = false;
    moveHistory.clear();

    // 初始化计时器
    blackTime = TIME_LIMIT;
    whiteTime = TIME_LIMIT;
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &GobangWindow::updateTimer);
    timer->start(1000); // 每秒更新一次
}

void GobangWindow::initUI()
{
    // 创建主部件
    QWidget *centralWidget = new QWidget(this);
    setCentralWidget(centralWidget);

    // 创建棋盘区域
    QWidget *boardWidget = new QWidget(centralWidget);
    boardWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    // 创建控制面板
    QWidget *controlPanel = new QWidget(centralWidget);
    controlPanel->setFixedWidth(200);

    // 创建UI组件
    blackTimeLabel = new QLabel(controlPanel);
    whiteTimeLabel = new QLabel(controlPanel);
    currentPlayerLabel = new QLabel(controlPanel);

    undoButton = new QPushButton("悔棋", controlPanel);
    restartButton = new QPushButton("重新开始", controlPanel);

    // 设置初始显示
    updateTimeDisplay();
    currentPlayerLabel->setText("当前回合: 黑方");
    currentPlayerLabel->setStyleSheet("font-weight: bold;");

    // 连接信号槽
    connect(undoButton, &QPushButton::clicked, this, &GobangWindow::onUndoClicked);
    connect(restartButton, &QPushButton::clicked, this, &GobangWindow::onRestartClicked);

    // 控制面板布局
    QVBoxLayout *controlLayout = new QVBoxLayout(controlPanel);
    controlLayout->addWidget(currentPlayerLabel);
    controlLayout->addWidget(blackTimeLabel);
    controlLayout->addWidget(whiteTimeLabel);
    controlLayout->addStretch();
    controlLayout->addWidget(undoButton);
    controlLayout->addWidget(restartButton);

    // 主布局
    QHBoxLayout *mainLayout = new QHBoxLayout(centralWidget);
    mainLayout->addWidget(boardWidget, 1);
    mainLayout->addWidget(controlPanel);
}

void GobangWindow::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);

    // 计算棋盘区域
    int boardWidth = BOARD_SIZE * CELL_SIZE + 2 * MARGIN;
    int boardHeight = BOARD_SIZE * CELL_SIZE + 2 * MARGIN;
    QRect boardRect((width() - boardWidth) / 2,
                    (height() - boardHeight) / 2,
                    boardWidth, boardHeight);

    // 绘制棋盘背景
    painter.fillRect(boardRect, QColor(222, 184, 135)); // 木质颜色

    // 绘制棋盘
    painter.translate(boardRect.topLeft());
    drawBoard(painter);
    drawPieces(painter);
    drawMarkers(painter);
}

void GobangWindow::drawBoard(QPainter &painter)
{
    painter.setPen(QPen(Qt::black, 1));

    // 绘制横线
    for (int i = 0; i < BOARD_SIZE; ++i) {
        painter.drawLine(MARGIN, MARGIN + i * CELL_SIZE,
                         MARGIN + (BOARD_SIZE - 1) * CELL_SIZE, MARGIN + i * CELL_SIZE);
    }

    // 绘制竖线
    for (int i = 0; i < BOARD_SIZE; ++i) {
        painter.drawLine(MARGIN + i * CELL_SIZE, MARGIN,
                         MARGIN + i * CELL_SIZE, MARGIN + (BOARD_SIZE - 1) * CELL_SIZE);
    }
}

void GobangWindow::drawPieces(QPainter &painter)
{
    for (int i = 0; i < BOARD_SIZE; ++i) {
        for (int j = 0; j < BOARD_SIZE; ++j) {
            if (board[i][j] == 1) { // 黑子
                painter.setBrush(Qt::black);
                painter.drawEllipse(QPoint(MARGIN + i * CELL_SIZE, MARGIN + j * CELL_SIZE),
                                    16, 16);
            } else if (board[i][j] == 2) { // 白子
                painter.setPen(QPen(Qt::black, 1));
                painter.setBrush(Qt::white);
                painter.drawEllipse(QPoint(MARGIN + i * CELL_SIZE, MARGIN + j * CELL_SIZE),
                                    16, 16);
            }
        }
    }
}

void GobangWindow::drawMarkers(QPainter &painter)
{
    // 绘制五个定位点
    painter.setBrush(Qt::black);
    int dots[5][2] = {{3, 3}, {3, 11}, {7, 7}, {11, 3}, {11, 11}};
    for (int i = 0; i < 5; ++i) {
        painter.drawEllipse(QPoint(MARGIN + dots[i][0] * CELL_SIZE,
                                   MARGIN + dots[i][1] * CELL_SIZE), 4, 4);
    }
}

void GobangWindow::mousePressEvent(QMouseEvent *event)
{
    if (gameOver || event->button() != Qt::LeftButton) {
        return;
    }

    // 转换为棋盘坐标
    QPoint boardPos = screenToBoard(event->pos());
    int x = boardPos.x();
    int y = boardPos.y();

    // 检查位置有效性
    if (!isValidPosition(x, y) || board[x][y] != 0) {
        return;
    }

    // 放置棋子
    placePiece(x, y);
}

QPoint GobangWindow::screenToBoard(const QPoint &pos) const
{
    // 计算棋盘区域
    int boardWidth = BOARD_SIZE * CELL_SIZE + 2 * MARGIN;
    int boardHeight = BOARD_SIZE * CELL_SIZE + 2 * MARGIN;
    QRect boardRect((width() - boardWidth) / 2,
                    (height() - boardHeight) / 2,
                    boardWidth, boardHeight);

    // 检查是否在棋盘内
    if (!boardRect.contains(pos)) {
        return QPoint(-1, -1);
    }

    // 转换为棋盘坐标
    int x = (pos.x() - boardRect.left() - MARGIN + CELL_SIZE / 2) / CELL_SIZE;
    int y = (pos.y() - boardRect.top() - MARGIN + CELL_SIZE / 2) / CELL_SIZE;

    return QPoint(x, y);
}

bool GobangWindow::isValidPosition(int x, int y) const
{
    return x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE;
}

void GobangWindow::placePiece(int x, int y)
{
    // 放置棋子
    board[x][y] = isBlackTurn ? 1 : 2;
    moveHistory.push(QPoint(x, y));

    // 检查胜利条件
    if (checkWin(x, y)) {
        endGame(isBlackTurn);
        return;
    }

    // 切换玩家
    switchPlayer();
    update();
}

bool GobangWindow::checkWin(int x, int y)
{
    // 检查四个方向
    return checkFiveInLine(x, y, 1, 0) ||  // 水平
           checkFiveInLine(x, y, 0, 1) ||  // 垂直
           checkFiveInLine(x, y, 1, 1) ||  // 对角线
           checkFiveInLine(x, y, 1, -1);   // 反对角线
}

bool GobangWindow::checkFiveInLine(int x, int y, int dx, int dy)
{
    int player = board[x][y];
    int count = 1;

    // 正向检查
    for (int i = 1; i < 5; ++i) {
        int nx = x + dx * i;
        int ny = y + dy * i;
        if (isValidPosition(nx, ny) && board[nx][ny] == player) {
            count++;
        } else {
            break;
        }
    }

    // 反向检查
    for (int i = 1; i < 5; ++i) {
        int nx = x - dx * i;
        int ny = y - dy * i;
        if (isValidPosition(nx, ny) && board[nx][ny] == player) {
            count++;
        } else {
            break;
        }
    }

    return count >= 5;
}

void GobangWindow::switchPlayer()
{
    isBlackTurn = !isBlackTurn;
    currentPlayerLabel->setText(isBlackTurn ? "当前回合: 黑方" : "当前回合: 白方");
}

void GobangWindow::endGame(bool blackWins)
{
    gameOver = true;
    timer->stop();

    if (blackWins) {
        showGameResult("黑方获胜!");
    } else {
        showGameResult("白方获胜!");
    }
}

void GobangWindow::updateTimer()
{
    if (isBlackTurn) {
        blackTime--;
        if (blackTime <= 0) {
            endGame(false); // 黑方超时，白方胜
        }
    } else {
        whiteTime--;
        if (whiteTime <= 0) {
            endGame(true); // 白方超时，黑方胜
        }
    }

    updateTimeDisplay();
}

void GobangWindow::updateTimeDisplay()
{
    QTime blackDisplay(0, blackTime / 60, blackTime % 60);
    QTime whiteDisplay(0, whiteTime / 60, whiteTime % 60);

    blackTimeLabel->setText("黑方时间: " + blackDisplay.toString("mm:ss"));
    whiteTimeLabel->setText("白方时间: " + whiteDisplay.toString("mm:ss"));
}

void GobangWindow::onUndoClicked()
{
    if (gameOver || moveHistory.isEmpty()) {
        return;
    }

    // 取出最后一步
    QPoint lastMove = moveHistory.pop();
    board[lastMove.x()][lastMove.y()] = 0;

    // 切换回合
    switchPlayer();
    update();
}

void GobangWindow::onRestartClicked()
{
    initGame();
    updateTimeDisplay();
    currentPlayerLabel->setText("当前回合: 黑方");
    update();
}

void GobangWindow::showGameResult(const QString &message)
{
    QMessageBox::information(this, "游戏结束", message);
}

void GobangWindow::resizeEvent(QResizeEvent *event)
{
    QMainWindow::resizeEvent(event);
    update();
}
